<?php

/**
 * Dispatcher
 * ==========
 * 
 *  The dispatcher is an object that aids in triggering the appropriate action when required. The dispatcher 
 *  also takes care of checking whether the user has enough permissions to request the action.
 *  
 *  A dispatcher is build by registering actions, with their authentification level (AuthLevel constants).
 *  In particular, also the default and the login action must be provided, if those will be used. Note: 
 *  Access control doesn't apply to them: they can be shown to anybody.
 *  
 *  Dispatching 
 *  
 *  Building a 
 *
 */

class AuthLevel {
	const NONE = 0;
	const USER = 1;
	const ADMIN = 2;
}

class ActionDispatcher {
	private $actions = array();
	private $default = null;
	private $login = null;
	private $blocked = null;
	
	public function register($action, $auth_level) {
		$this->actions[$action->get_name()] = array($auth_level, $action);
	}
	
	public function register_default($action) {
		$this->default = $action;
	}
	
	public function register_login($action) {
		$this->login = $action;
	}
	
	public function register_blocked($action) {
		$this->blocked = $action;
	}
	
	public function dispatch($action_name, $auth_level) {
		
		try {
		
			// Use the default if applicable
			if ($action_name == '' or !isset($this->actions[$action_name])) {
				$this->dispatch_directly($this->default);
			}
			
			else {
				list($required_auth_level, $action) = $this->actions[$action_name];
				
				// Serve login if authentification level is insufficient
				if ($required_auth_level > $auth_level) {
					$this->dispatch_directly($this->login);
				}
				else {
					$this->dispatch_directly($action);
				}		
			}
		
		} catch (Exception $e) {
			
			report_error($e->getMessage(), $e->getTrace());
			if (defined('DEBUG') and DEBUG) {
				throw $e;
			}
			
		}
		
	}
	
	private function dispatch_directly($action) {
		
		$view = $action->check_and_handle_request($_REQUEST);
		
		if ($view === null) {
			throw new Exception("Action forgot to return a view!");
		}
		
		$view->send();
		exit();
		
	}
	
	public function dispatch_blocked() {
		$this->dispatch_directly($this->blocked);
	}
}

?>